package com.atguigu.tingshu.order.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import com.atguigu.tingshu.account.client.UserAccountFeignClient;
import com.atguigu.tingshu.album.client.AlbumInfoFeignClient;
import com.atguigu.tingshu.album.client.TrackInfoFeignClient;
import com.atguigu.tingshu.common.constant.RabbitConstant;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.util.AssertUtil;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.order.OrderDerate;
import com.atguigu.tingshu.model.order.OrderDetail;
import com.atguigu.tingshu.model.order.OrderInfo;
import com.atguigu.tingshu.model.user.VipServiceConfig;
import com.atguigu.tingshu.order.helper.SignHelper;
import com.atguigu.tingshu.order.mapper.OrderDerateMapper;
import com.atguigu.tingshu.order.mapper.OrderDetailMapper;
import com.atguigu.tingshu.order.mapper.OrderInfoMapper;
import com.atguigu.tingshu.order.service.OrderInfoService;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.user.client.VipServiceConfigFeignClient;
import com.atguigu.tingshu.vo.account.AccountLockVo;
import com.atguigu.tingshu.vo.album.AlbumListVo;
import com.atguigu.tingshu.vo.order.OrderDerateVo;
import com.atguigu.tingshu.vo.order.OrderDetailVo;
import com.atguigu.tingshu.vo.order.OrderInfoVo;
import com.atguigu.tingshu.vo.order.TradeVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})

//    订单付款项目类型 1001-专辑 1002-声音 1003-vip会员
//    public static final String  ORDER_ITEM_TYPE_ALBUM="1001";  // 专辑
//    public static final String  ORDER_ITEM_TYPE_TRACK="1002";  // 声音
//    public static final String  ORDER_ITEM_TYPE_VIP="1003";  // vip会员
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {

    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private VipServiceConfigFeignClient vipServiceConfigFeignClient;
    @Autowired
    private AlbumInfoFeignClient albumInfoFeignClient;
    @Autowired
    private TrackInfoFeignClient trackInfoFeignClient;
    @Autowired
    private UserInfoFeignClient userInfoFeignClient;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private OrderDerateMapper orderDerateMapper;
    @Autowired
    private UserAccountFeignClient userAccountFeignClient;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    public OrderInfoVo trade(TradeVo tradeVo) {

        // 获取itemId
        // 获取类型 itemType 001-专辑 1002-声音 1003-vip会员
        // 获取 数量 trackCount 仅针对声音
        OrderInfoVo orderInfoVo = new OrderInfoVo();
        switch (tradeVo.getItemType()) {
            // 购买的是vip
            case SystemConstant.ORDER_ITEM_TYPE_VIP:
                orderInfoVo = tradeVip(tradeVo);
                break;
            // 购买的是专辑
            case SystemConstant.ORDER_ITEM_TYPE_ALBUM:
                orderInfoVo = tradeAlbum(tradeVo);
                break;
            // 购买的是声音
            case SystemConstant.ORDER_ITEM_TYPE_TRACK:
                orderInfoVo = tradeTrack(tradeVo);
                break;
        }

        // 三种情况
        // 1. 购买的是vip

        // 2. 购买的是整张专辑

        // 3. 购买的是声音
        return orderInfoVo;
    }

    // 开启全局事务
    @GlobalTransactional
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String submitOrder(OrderInfoVo orderInfoVo) {
        // 1. 验证签名 防止数据被篡改 和 订单过期
        checkSign(orderInfoVo);
        // 2. 幂等性 生成订单的时候往redis保存了 tradeNo
        // 获取 tradeNo 并且校验是否存在 且 判断value是否相等
        checkIdempotent(orderInfoVo);

        // 3. 判断支付方式  余额支付  三方支付
        //   "支付方式：1101-微信 1102-支付宝 1103-账户余额"
        // 如果是余额支付 则直接处理
        // 如果是第三方支付还需要调用第三方接口,并且等待回调
        String payWay = orderInfoVo.getPayWay();
        if (SystemConstant.ORDER_PAY_WAY_ACCOUNT.equals(payWay)) {
            // 余额支付
            // 1. 直接校验余额并且扣除余额(快速支付)
            // 远程调用account 服务
            AccountLockVo accountLockVo = new AccountLockVo();
            accountLockVo.setUserId(AuthContextHolder.getUserId());
            accountLockVo.setOrderNo(orderInfoVo.getTradeNo());
            accountLockVo.setAmount(orderInfoVo.getOrderAmount());
            accountLockVo.setContent(getOrderTitle(orderInfoVo));
            // 远程调用account服务 检查余额并扣除余额
            Result checkAndDeductAmountResultant = userAccountFeignClient.checkAndDeductAmount(accountLockVo);
            // 远程调用成功则成功
            AssertUtil.resultAssert(checkAndDeductAmountResultant, ResultCodeEnum.ACCOUNT_LESS);
            // 2. 保存订单 保存订单数据和订单详情数据以及订单减免数据到数据库
            this.saveOrder(orderInfoVo);
            // 3. 余额扣除成功 保存交易记录  (用户可以查询是否购买过该商品)
            // 远程调用user服务 保存交易记录
            UserPaidRecordVo userPaidRecordVo = new UserPaidRecordVo();
            userPaidRecordVo.setUserId(AuthContextHolder.getUserId());
            userPaidRecordVo.setOrderNo(orderInfoVo.getTradeNo());
            userPaidRecordVo.setItemType(orderInfoVo.getItemType());
            // 设置购买的商品id列表
            // 如果购买的是 vip 和 专辑 id 只有一个
            // 如果购买的是声音 id 有多个
            // 返回商品id列表
            List<Long> itemIds = orderInfoVo.getOrderDetailVoList().stream().map(OrderDetailVo::getItemId).toList();
            userPaidRecordVo.setItemIdList(itemIds);
            // 远程调用user服务 保存交易记录
            Result userPaidRecordResult = userInfoFeignClient.saveUserPaidRecord(userPaidRecordVo);
            // AssertUtil.resultAssert(userPaidRecordResult, ResultCodeEnum.DATA_ERROR);
        } else {
            // 第三方支付(默认微信)
            // 不需要保存交易记录 不需要扣除余额
            this.saveOrder(orderInfoVo);

        }
        return orderInfoVo.getTradeNo();
    }

    // 支付成功查看订单详情
    @Override
    public OrderInfo getOrderInfo(String orderNo) {
        // 1. 查询订单的基本信息
        OrderInfo orderInfo = orderInfoMapper.selectOne(new LambdaQueryWrapper<OrderInfo>()
                .eq(OrderInfo::getOrderNo, orderNo)
                .eq(OrderInfo::getUserId, AuthContextHolder.getUserId()));
        if (orderInfo == null) {
            throw new GuiguException("查询的订单不存在");
        }
        // 2. 查看订单的明细列表
        List<OrderDetail> orderDetailList = orderDetailMapper.selectList(new LambdaQueryWrapper<OrderDetail>()
                .eq(OrderDetail::getOrderId, orderInfo.getId()));
        orderInfo.setOrderDetailList(orderDetailList);
        // 3. 查看订单的减免列表
        List<OrderDerate> orderDerateList = orderDerateMapper.selectList(new LambdaQueryWrapper<OrderDerate>()
                .eq(OrderDerate::getOrderId, orderInfo.getId()));
        orderInfo.setOrderDerateList(orderDerateList);
        // 其他属性
        String orderStatusName = "";
        switch (orderInfo.getOrderStatus()) {
            case SystemConstant.ORDER_STATUS_PAID:
                orderStatusName = "已支付";
                break;
            case SystemConstant.ORDER_STATUS_UNPAID:
                orderStatusName = "未支付";
                break;
            case SystemConstant.ORDER_STATUS_CANCEL:
                orderStatusName = "已取消";
                break;
        }
        String payWayName = "";
        switch (orderInfo.getPayWay()) {
            case SystemConstant.ORDER_PAY_WAY_WEIXIN:
                payWayName = "微信支付";
                break;
            case SystemConstant.ORDER_PAY_WAY_ACCOUNT:
                payWayName = "账户余额支付";
                break;
            case SystemConstant.ORDER_PAY_WAY_ALIPAY:
                payWayName = "支付宝支付";
                break;
        }


        orderInfo.setOrderStatusName(orderStatusName);
        orderInfo.setPayWayName(payWayName);
        orderInfo.setOrderTitle(getOrderTitle(orderInfo));
        return orderInfo;
    }


    // 分页查询用户的订单列表 包含订单详情列表 包含订单减免列表
    @Override
    public Page<OrderInfo> findUserOrderPage(Long pageNum, Long pageSize) {
        Page<OrderInfo> page = orderInfoMapper.findUserOrderPage(new Page<OrderInfo>(pageNum, pageSize), AuthContextHolder.getUserId());
        return page;
    }


    // 自定义方法
    // 1. 购买vip
    private OrderInfoVo tradeVip(TradeVo tradeVo) {
        // 创建 OrderInfoVo 组装数据并返回
        OrderInfoVo orderInfoVo = new OrderInfoVo();

        // 获取itemId
        Long itemId = tradeVo.getItemId(); // vipId
        // 远程调用 user服务查询需要购买的vip方案的信息
        Result<VipServiceConfig> vipConfigResult = vipServiceConfigFeignClient.findVipById(itemId);
        AssertUtil.resultAssert(vipConfigResult, ResultCodeEnum.DATA_ERROR);
        VipServiceConfig vipConfig = vipConfigResult.getData();

        // 组装数据
        // 1. 交易号
        orderInfoVo.setTradeNo(createTradeNo());
        // 2. 支付方式 默认微信
        orderInfoVo.setPayWay(SystemConstant.ORDER_PAY_WAY_WEIXIN);
        // 3. 付款项目类型 1001-专辑 1002-声音 1003-vip会员
        orderInfoVo.setItemType(SystemConstant.ORDER_ITEM_TYPE_VIP);
        // 4. 订单原价
        orderInfoVo.setOriginalAmount(vipConfig.getPrice());
        // 5. 订单减免金额
        orderInfoVo.setDerateAmount(vipConfig.getPrice().subtract(vipConfig.getDiscountPrice()));
        // 6. 订单优惠后价格
        orderInfoVo.setOrderAmount(vipConfig.getDiscountPrice());

        // 7. 订单明细列表
        List<OrderDetailVo> orderDetailVoList = new ArrayList<>();
        OrderDetailVo orderDetailVo = new OrderDetailVo();
        orderDetailVo.setItemId(vipConfig.getId());
        orderDetailVo.setItemName(vipConfig.getName());
        orderDetailVo.setItemUrl(vipConfig.getImageUrl());
        orderDetailVo.setItemPrice(vipConfig.getPrice());
        orderDetailVoList.add(orderDetailVo);
        orderInfoVo.setOrderDetailVoList(orderDetailVoList);
        // 8. 订单减免明细列表
        List<OrderDerateVo> orderDerateVoList = new ArrayList<>();
        OrderDerateVo orderDerateVo = new OrderDerateVo();
        orderDerateVo.setDerateType(SystemConstant.ORDER_DERATE_VIP_SERVICE_DISCOUNT);
        orderDerateVo.setDerateAmount(vipConfig.getPrice().subtract(vipConfig.getDiscountPrice()));
        orderDerateVo.setRemarks("会员服务优惠");
        orderDerateVoList.add(orderDerateVo);
        orderInfoVo.setOrderDerateVoList(orderDerateVoList);
        // 9. 时间戳 防止重复提交
        orderInfoVo.setTimestamp(System.currentTimeMillis());
        // 10 . 签名 防止数据被篡改
        orderInfoVo.setSign(getSign(orderInfoVo));

        return orderInfoVo;
    }

    // 购买整张专辑
    private OrderInfoVo tradeAlbum(TradeVo tradeVo) {
        // 创建 OrderInfoVo 组装数据并返回
        OrderInfoVo orderInfoVo = new OrderInfoVo();
        // 获取itemId
        Long itemId = tradeVo.getItemId(); // vipId
        // 远程调用 album服务 查询专辑的信息
        Result<AlbumInfo> albumInfoResult = albumInfoFeignClient.getAlbumInfoById2(itemId);
        AssertUtil.resultAssert(albumInfoResult, ResultCodeEnum.DATA_ERROR);
        AlbumInfo albumInfo = albumInfoResult.getData();
        // 1. 订单交易号
        orderInfoVo.setTradeNo(createTradeNo());
        // 2. 支付方式 默认微信
        orderInfoVo.setPayWay(SystemConstant.ORDER_PAY_WAY_WEIXIN);
        // 3. 付款项目类型 1001-专辑 1002-声音 1003-vip会员
        orderInfoVo.setItemType(SystemConstant.ORDER_ITEM_TYPE_ALBUM);
        // 4. 订单原价
        // 获取声音数量
        Integer trackCount = albumInfo.getIncludeTrackCount();
        // 获取收费的声音数量
        Integer chargeTrackCount = albumInfo.getIncludeTrackCount() - albumInfo.getTracksForFree();
        // 订单原始金额
        BigDecimal originalAmount = albumInfo.getPrice().multiply(new BigDecimal(chargeTrackCount));
        orderInfoVo.setOriginalAmount(originalAmount);
        // 最终折扣
        BigDecimal finalDiscount = getFinalDiscount(albumInfo, AuthContextHolder.getUserId());
        // 6. 订单优惠后价格
        BigDecimal orderAmount = originalAmount.multiply(finalDiscount);
        orderInfoVo.setOrderAmount(orderAmount);
        // 5. 订单减免金额
        orderInfoVo.setDerateAmount(originalAmount.subtract(orderAmount));
        // 7. 订单明细列表
        List<OrderDetailVo> orderDetailVoList = new ArrayList<>();
        OrderDetailVo orderDetailVo = new OrderDetailVo();
        orderDetailVo.setItemId(albumInfo.getId());
        orderDetailVo.setItemName(albumInfo.getAlbumTitle());
        orderDetailVo.setItemUrl(albumInfo.getCoverUrl());
        orderDetailVo.setItemPrice(originalAmount);
        orderDetailVoList.add(orderDetailVo);
        orderInfoVo.setOrderDetailVoList(orderDetailVoList);
        // 8. 订单减免明细列表
        List<OrderDerateVo> orderDerateVoList = new ArrayList<>();
        OrderDerateVo orderDerateVo = new OrderDerateVo();
        orderDerateVo.setDerateType(SystemConstant.ORDER_DERATE_ALBUM_DISCOUNT);
        orderDerateVo.setDerateAmount(originalAmount.subtract(orderAmount));
        orderDerateVo.setRemarks("专辑优惠");
        orderDerateVoList.add(orderDerateVo);
        orderInfoVo.setOrderDerateVoList(orderDerateVoList);
        // 9. 时间戳 防止重复提交
        orderInfoVo.setTimestamp(System.currentTimeMillis());
        // 10. 签名 防止数据被篡改
        orderInfoVo.setSign(getSign(orderInfoVo));
        return orderInfoVo;
    }

    // 创建方法生成声音订单
    private OrderInfoVo tradeTrack(TradeVo tradeVo) {
        // 创建 OrderInfoVo 组装数据并返回
        OrderInfoVo orderInfoVo = new OrderInfoVo();
        // 获取itemId
        Long itemId = tradeVo.getItemId();
        // 远程调用 根据声音id查询声音信息
        Result<TrackInfo> trackInfoResult = trackInfoFeignClient.getTrackInfoInner(itemId);
        AssertUtil.resultAssert(trackInfoResult, ResultCodeEnum.DATA_ERROR);
        TrackInfo trackInfo = trackInfoResult.getData();
        // 远程调用获取声音所属专辑
        Result<AlbumInfo> albumInfoResult = albumInfoFeignClient.getAlbumInfoById2(trackInfo.getAlbumId());
        AssertUtil.resultAssert(albumInfoResult, ResultCodeEnum.DATA_ERROR);
        AlbumInfo albumInfo = albumInfoResult.getData();

        // 获取购买声音的数量 0 当前集  5 后5级别
        Integer trackCount = tradeVo.getTrackCount();
        if (trackCount == 0) {
            trackCount = 1;
        }
        // 1. 生成订单交易号
        orderInfoVo.setTradeNo(createTradeNo());
        // 2. 支付方式 默认微信
        orderInfoVo.setPayWay(SystemConstant.ORDER_PAY_WAY_WEIXIN);
        // 3. 付款项目类型 1001-专辑 1002-声音 1003-vip会员
        orderInfoVo.setItemType(SystemConstant.ORDER_ITEM_TYPE_TRACK);
        // 4. 订单原价 单个专辑的原价
        BigDecimal originalAmount = albumInfo.getPrice().multiply(new BigDecimal(trackCount));
        orderInfoVo.setOriginalAmount(originalAmount);
        // 5. 订单优惠后价格
        BigDecimal finalDiscount = getFinalDiscount(albumInfo, AuthContextHolder.getUserId());
        BigDecimal orderAmount = originalAmount.multiply(finalDiscount);
        orderInfoVo.setOrderAmount(orderAmount);
        // 6. 订单减免金额
        orderInfoVo.setDerateAmount(originalAmount.subtract(orderAmount));
        // 远程调用
        // 查询该专辑的所有声音列表 需要的参数   albumId  getOrderNum count
        Result<List<TrackInfo>> trackInfoListResult = trackInfoFeignClient.getNeedTrackInfoList(albumInfo.getId(), trackInfo.getOrderNum(), trackCount);
        AssertUtil.resultAssert(trackInfoListResult, ResultCodeEnum.DATA_ERROR);
        List<TrackInfo> trackInfoList = trackInfoListResult.getData();

        // 7. 订单明细列表
        List<OrderDetailVo> orderDetailVoList = new ArrayList<>();
        trackInfoList.forEach(item -> {
            OrderDetailVo orderDetailVo = new OrderDetailVo();
            orderDetailVo.setItemId(item.getId());
            orderDetailVo.setItemName(item.getTrackTitle());
            orderDetailVo.setItemUrl(item.getCoverUrl());
            orderDetailVo.setItemPrice(albumInfo.getPrice());
            orderDetailVoList.add(orderDetailVo);
        });
        orderInfoVo.setOrderDetailVoList(orderDetailVoList);
        // 8. 订单减免明细列表
        List<OrderDerateVo> orderDerateVoList = new ArrayList<>();
        trackInfoList.forEach(item -> {
            OrderDerateVo orderDerateVo = new OrderDerateVo();
            orderDerateVo.setDerateType(SystemConstant.ORDER_DERATE_ALBUM_DISCOUNT);
            orderDerateVo.setDerateAmount(albumInfo.getPrice().subtract(albumInfo.getPrice().multiply(finalDiscount)));
            orderDerateVo.setRemarks("声音优惠");
            orderDerateVoList.add(orderDerateVo);
        });
        orderInfoVo.setOrderDerateVoList(orderDerateVoList);
        // 9. 时间戳 防止重复提交
        orderInfoVo.setTimestamp(System.currentTimeMillis());
        // 10. 签名 防止数据被篡改
        orderInfoVo.setSign(getSign(orderInfoVo));
        return orderInfoVo;
    }


    // 创建方法生成订单交易号
    public String createTradeNo() {

        // 生成交易订单号 并存入缓存 可以避免订单的重复提交
        String tradeNo = IdUtil.getSnowflakeNextIdStr();
        // key
        String key = RedisConstant.TRADE_NO_KEY + AuthContextHolder.getUserId();
        redisTemplate.opsForValue().set(key, tradeNo, RedisConstant.TRADE_NO_TIMEOUT, TimeUnit.SECONDS);
        return tradeNo;
    }

    public boolean isVipUser(Long userId) {
        Result<UserInfoVo> userInfoResult = userInfoFeignClient.getUserInfoById(userId);
        AssertUtil.resultAssert(userInfoResult, ResultCodeEnum.DATA_ERROR);
        UserInfoVo userInfoVo = userInfoResult.getData();
        if (userInfoVo.getIsVip().equals(1) && userInfoVo.getVipExpireTime().after(new Date())) {
            return true;
        }
        return false;
    }

    // 生成签名
    public String getSign(OrderInfoVo orderInfoVo) {
        // 对象转换器 将一个类型的对象转换为另一个类型的对象  对象转换为json -- 另一个对象 JKSON提供
        ObjectMapper objectMapper = new ObjectMapper();
        String sign = SignHelper.getSign(objectMapper.convertValue(orderInfoVo, Map.class));
        return sign;
    }

    // 验证签名
    public boolean checkSign(OrderInfoVo orderInfoVo) {
        // 获取签名
        ObjectMapper objectMapper = new ObjectMapper();
        Map map = objectMapper.convertValue(orderInfoVo, Map.class);
        map.put("payWay", SystemConstant.ORDER_PAY_WAY_WEIXIN);
        // 验证签名
        SignHelper.checkSign(map);
        return true;
    }

    // 校验幂等性
    public boolean checkIdempotent(OrderInfoVo orderInfoVo) {
        // 检查key是否存在
        // 比较 tradeNo 是否相同
        // 如果是第一次提交 则 key存在,且相等 删除缓存  为了保证原子性需要使用lua脚本
        // 如果不是第一次提交 则 key不存在或者tradeNo不相等 则返回false
        String tradeNo = orderInfoVo.getTradeNo();
        String key = RedisConstant.TRADE_NO_KEY + AuthContextHolder.getUserId();

        String checkLua = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Boolean flag = (Boolean) redisTemplate.execute(new DefaultRedisScript(checkLua, Boolean.class), Arrays.asList(key), tradeNo);
        if (!flag) {
            // 拒绝消息
            throw new GuiguException(ResultCodeEnum.ORDER_SUBMIT_REPEAT);
        }
        return flag;

    }

    // 保存订单
    //OrderInfo 中有但 OrderInfoVo 中没有的属性：
    //userId - 用户ID
    //orderTitle - 订单标题
    //orderNo - 订单号
    //orderStatus - 订单状态（未支付/已支付/已取消）
    //orderStatusName - 订单状态名称（显示用）
    //payWayName - 支付方式名称（显示用）
    @Transactional(rollbackFor = Exception.class)
    public void saveOrder(OrderInfoVo orderInfoVo) {
        OrderInfo orderInfo = new OrderInfo();
        BeanUtils.copyProperties(orderInfoVo, orderInfo);
        // 1. 获取用户id 并设置用户的id
        Long userId = AuthContextHolder.getUserId();
        orderInfo.setUserId(userId);
        // 2. 设置订单号
        orderInfo.setOrderNo(orderInfoVo.getTradeNo());
        // 3. 设置订单标题
        orderInfo.setOrderTitle(getOrderTitle(orderInfoVo));
        // 4. 设置订单的状态 如果是本地支付 可以直接设置为 已支付  如果是第三方支付 则设置为 未支付(需要调用第三方接口,回调支付的结果)
        String payWay = orderInfoVo.getPayWay();
        String status = payWay.equals(SystemConstant.ORDER_PAY_WAY_WEIXIN) ? SystemConstant.ORDER_STATUS_UNPAID : SystemConstant.ORDER_STATUS_PAID;
        orderInfo.setOrderStatus(status);
        // 5. 设置订单状态名称 根据订单类型判断
        orderInfo.setOrderStatusName(orderInfo.getOrderStatus().equals(SystemConstant.ORDER_STATUS_PAID) ? "已支付" : "未支付");
        // 6. 设置支付方式名称
        orderInfo.setPayWayName(SystemConstant.ORDER_PAY_WAY_WEIXIN.equals(payWay) ? "微信支付" : "余额支付");
        // (1) 保存订单 并且生成订单id 保存订单明细 保存订单减免明细 需要使用订单id
        orderInfoMapper.insert(orderInfo);
        // (2) 保存订单明细
        orderInfoVo.getOrderDetailVoList().forEach(orderDetailVo -> {
            OrderDetail orderDetail = new OrderDetail();
            BeanUtils.copyProperties(orderDetailVo, orderDetail);
            orderDetail.setOrderId(orderInfo.getId());
            orderDetailMapper.insert(orderDetail);
        });
        // (3) 保存订单减免明细
        orderInfoVo.getOrderDerateVoList().forEach(orderDerateVo -> {
            OrderDerate orderDerate = new OrderDerate();
            BeanUtils.copyProperties(orderDerateVo, orderDerate);
            orderDerate.setOrderId(orderInfo.getId());
            orderDerateMapper.insert(orderDerate);
        });
        // 4. 三方支付 延时关闭订单 通过延时队列
        if (SystemConstant.ORDER_PAY_WAY_WEIXIN.equals(payWay)) {
            // 延时关闭订单
            if (SystemConstant.ORDER_PAY_WAY_WEIXIN.equals(payWay)) {
                // 延时关闭订单
                rabbitTemplate.convertAndSend(RabbitConstant.ORDER_EXCHANGE, RabbitConstant.ORDER_TTL_RK, orderInfo.getOrderNo());
            }
        }
    }

    // 根据类型返回订单标题
    public String getOrderTitle(OrderInfoVo orderInfoVo) {
        String orderTitle = "";
        switch (orderInfoVo.getItemType()) {
            case SystemConstant.ORDER_ITEM_TYPE_ALBUM:
                orderTitle = "购买了专辑: " + orderInfoVo.getOrderDetailVoList().get(0).getItemName();
                break;
            case SystemConstant.ORDER_ITEM_TYPE_TRACK:
                orderTitle = "购买了声音: " + orderInfoVo.getOrderDetailVoList().get(0).getItemName() + "等声音";
                break;
            case SystemConstant.ORDER_ITEM_TYPE_VIP:
                orderTitle = "购买了vip: " + orderInfoVo.getOrderDetailVoList().get(0).getItemName();
                break;
        }
        return orderTitle;
    }

    public String getOrderTitle(OrderInfo orderInfo) {
        String orderTitle = "";
        switch (orderInfo.getItemType()) {
            case SystemConstant.ORDER_ITEM_TYPE_ALBUM:
                orderTitle = "购买了专辑: " + orderInfo.getOrderDetailList().get(0).getItemName();
                break;
            case SystemConstant.ORDER_ITEM_TYPE_TRACK:
                orderTitle = "购买了声音: " + orderInfo.getOrderDetailList().get(0).getItemName() + "等声音";
                break;
            case SystemConstant.ORDER_ITEM_TYPE_VIP:
                orderTitle = "购买了vip: " + orderInfo.getOrderDetailList().get(0).getItemName();
                break;
        }
        return orderTitle;
    }

    // 创建方法生成最终折扣
    public BigDecimal getFinalDiscount(AlbumInfo albumInfo, Long userId) {
        // 判断当前用户是否为vip用户
        boolean vipUser = isVipUser(userId);
        // 1. 判断是否有普通折扣
        boolean isDiscount = albumInfo.getDiscount().compareTo(new BigDecimal(-1)) > 0;
        // 2. 判断是否有vip折扣
        boolean isVipDiscount = albumInfo.getVipDiscount().compareTo(new BigDecimal(-1)) > 0;
        // 3. 定义最终折扣
        BigDecimal finalDiscount = new BigDecimal(1);
        // 当前用户为vip用户
        if (vipUser) {
            if (isDiscount) {
                // 如果有普通折扣
                if (isVipDiscount) {
                    // 如果有vip折扣
                    // 更清晰的写法
                    BigDecimal vipDiscount = albumInfo.getVipDiscount();
                    BigDecimal normalDiscount = albumInfo.getDiscount();
                    boolean isVipMoreFavorable = vipDiscount.compareTo(normalDiscount) < 0;
                    finalDiscount = isVipMoreFavorable ? vipDiscount.divide(new BigDecimal(10)) : normalDiscount.divide(new BigDecimal(10));

                } else {
                    // 如果没有vip折扣
                    finalDiscount = albumInfo.getDiscount().divide(new BigDecimal(10));
                }
            } else {
                // 如果没有普通折扣
                if (isVipDiscount) {
                    // 如果有vip折扣
                    finalDiscount = albumInfo.getVipDiscount().divide(new BigDecimal(10));
                } else {
                    // 如果没有vip折扣
                    finalDiscount = new BigDecimal(1);
                }

            }

            // 用户不是vip用户
        } else {
            if (isDiscount) {
                // 如果有普通折扣
                finalDiscount = albumInfo.getDiscount().divide(new BigDecimal(10));
            } else {
                // 如果没有普通折扣
                finalDiscount = new BigDecimal(1);
            }
        }
        return finalDiscount;
    }
}
